/*********************************************************************************
 *      Copyright:  (C) 2025 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(2025年04月15日)
 *         Author:  chenhongyu0822@163.com
 *      ChangeLog:  1, Release initial version on "2025年04月15日 09时45分07秒"
 *                 
 ********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <libgen.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <ctype.h>
#include <sqlite3.h>

#include "server.h"
#include "database.h"

#define	    max_events             512
#define		array_size(x)           (sizeof(x)/sizeof(x[0]))
#define     MSG                    "Receive successfully!\n"

int main (int argc, char **argv)
{
	int                               daemon_run=0;
	char                              *program=NULL;
	int                               opt;
	int                               serv_port=0;
	int                               listen_fd,connect_fd;
	int                               epollfd;
	struct epoll_event                event;
	struct epoll_event                event_array[max_events];
	int                               event_count;
	int                               rv;
	int                               i,j;
	int                               found;
	char                              buf[1024];
    char                              rpi[50];
	float                             temp;
	int                               time;
	sqlite3                           *db;
	struct option                     long_options[]={
		{"daemon", no_argument, NULL, 'b'},
		{"port", required_argument, NULL, 'p'},
		{"help", no_argument, NULL, 'h'},
		{"NULL, 0, NULL, 0"},
	};

	program=basename(argv[0]);

	while((opt =getopt_long(argc, argv, "b:p:h", long_options, NULL))!=-1)
	{
		switch(opt)
		{
			case 'b':
				daemon_run=1;
				break;
			case 'p':
				serv_port=atoi(optarg);
				break;
			case 'h':
				print_usage(program);
				return EXIT_SUCCESS;
			default:
				break;
		}
	}

	if(!serv_port)
	{
		print_usage(program);
		return -1;
	}
	
	if(database_init("database.db", &db)<0)
	{
		printf("Database initialization failure:%s\n", strerror(errno));
	}

	if((listen_fd=server_init(NULL, serv_port))<0)
	{
		printf("Error :server listen on port %d failure:%s\n", 
				serv_port, strerror(errno));
		return -2;
	}

	printf("server start to listen on port %d successfully!\n",
			serv_port);

	if(daemon_run)
	{
		daemon(0,0);
	}

	if((epollfd=epoll_create(max_events))<0)
	{
		printf("epoll_create()failure:%s\n", strerror(errno));
		return -3;
	}
	
	event.events=EPOLLIN;
	event.data.fd=listen_fd;

	if(epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_fd, &event)<0)
	{
		printf("epoll add listen socket failure:%s\n", strerror(errno));
		return -4;
	}
	
	while(1)
	{
		event_count=epoll_wait(epollfd, event_array, max_events, -1);
		if(event_count<0)
		{
			printf("epoll failure:%s\n", strerror(errno));
			break;
		}
		else if(event_count==0)
		{
			printf("epoll get timeout\n");
			continue;
		}

		for(i=0; i<event_count; i++)
		{
			if((event_array[i].events&EPOLLERR)||(event_array[i].events&EPOLLHUP))
			{
				printf("epoll wait get error on fd[%d]:%s\n",
						event_array[i].data.fd, strerror(errno));
				epoll_ctl(epollfd,EPOLL_CTL_DEL, event_array[i].data.fd, NULL);
				close(event_array[i].data.fd);

			}
			if(event_array[i].data.fd==listen_fd)
			{
				if((connect_fd=accept(listen_fd, (struct sockaddr *)NULL, NULL))<0)
				{
					printf("accept new client failure:%s\n", strerror(errno));

				}
				event.data.fd=connect_fd;
				event.events=EPOLLIN;
				if(epoll_ctl(epollfd, EPOLL_CTL_ADD,connect_fd, &event)<0)
				{
					printf("epoll add client socket failure:%s\n", strerror(errno));
					close(event_array[i].data.fd);
					continue;
				}
				printf("epoll add new client socket[%d]ok.\n", connect_fd);
			}
			else
			{
				memset(buf, 0, sizeof(buf));	
				if((rv=read(event_array[i].data.fd,buf, sizeof(buf)))<=0)
				{
					printf("socket[%d] read failure or get disconncet and will be remove\n", 
							event_array[i].data.fd);
					epoll_ctl(epollfd,EPOLL_CTL_DEL, event_array[i].data.fd, NULL);
					close(event_array[i].data.fd);
					continue;
				}
				else
				{	

					printf("socket[%d] read get information from client:%s\n",
							event_array[i].data.fd, buf);            
		
					if(insert_data(db, buf)<0)
					{
						printf("Save data failure:%s\n", strerror(errno));
					}
					else
					{
						printf("Save data successfully!\n");
					}
					
					if(write(event_array[i].data.fd, MSG, strlen(MSG))<0)
					{
						printf("socket[%d] write failure:%s\n", 
								event_array[i].data.fd, strerror(errno));
						epoll_ctl(epollfd,EPOLL_CTL_DEL, event_array[i].data.fd, NULL);
						close(event_array[i].data.fd);
					}
				}
			}
		
		}

	}
	close(listen_fd);
    sqlite3_close(db);
	return 0;
} 



